#ifndef fWML_H_
#define fWML_H_

//#include <TXTFRMAT.H>
#include "fXmlParser.h"
#include <e32base.h>

// INCLUDES
//////////////////////////////////////////////////////////////////////////////
//  Sax method
// -----> fWml(definition)
//
//////////////////////////////////////////////////////////////////////////////
// class CBrowserFont
// {
// public:
//     TCharFormat iCharFormat;
//     TCharFormatMask iCharFormatMask;
//     TInt _wholeSize;
//
//     static CBrowserFont *DefaultFont();
//     static CBrowserFont *AchorFont();
//     static CBrowserFont *FocusAchorFont();
//     static CBrowserFont *InputFont();
//     static CBrowserFont *FocusInputFont();
// };

class CElementBase : public CBase
{
public:
    CElementBase( )
    {
        iText = NULL;
    }
    
    virtual ~ CElementBase( );
    HBufC *GetText( )
    {
        return iText;
    }
    
    void SetText( const TDesC & text )
    {
        delete iText;
        
        iText = HBufC::NewL( text.Length( ) );
        iText->Des( ).Copy( text );
    }
    void AppendText( const TDesC & text )
    {
        if( iText->Des( ).MaxLength( ) < iText->Length( ) + text.Length( ) )
        {
            iText = iText->ReAlloc( iText->Length( ) + text.Length( ) );
            iText->Des( ).Append( text );
        }
    }
    const TDesC & GetAttribute( const TDesC & name );
    void AddAttribute( const TDesC & aNamespace, const TDesC & name, const TDesC & value );
    void AddAttribute( CXmlAttribute * attr );
    void SetAttribute( const TDesC & aNamespace, const TDesC & name, const TDesC & value );

protected:
    RAttributeList iAttrList;
    HBufC *iText;
};

//////////////////////////////////////////////////////////////////////////////
//  Dom method
// -----> CElement(definition)
//
//////////////////////////////////////////////////////////////////////////////
using namespace Eaxp;
class CElement : public CElementBase
{
public:
    ~CElement( );

    static CElement *NewLC( const TDesC & name );
    static CElement *NewL( const TDesC & name );
    void ConstructL( );
    const TDesC & GetName( ) const
    {
        return *iName;
    }
    
    inline const TDesC & GetElmentText( )
    {
        if( iName->Compare( _L("Text") ) == 0 )
            return *iText;
        else
            for( TInt i = 0; i < ElementCount( ); i++ )
            {
                if( iElementArray[ i ]->iName->Compare( _L("Text") ) == 0 )
                {
                    return *iElementArray[ i ]->iText;
                }
            }
        
        return KNullDesC;
    }
    float GetElementTextAsFloat( )
    {
        float value = 0.00;
        if( iName->Compare( _L("Text") ) == 0 )
        {
            TLex lex( *iText );
            int result = lex.Val( value );
            return result == KErrNone ? value : 0.00;
        }
        else
        {
            for( TInt i = 0; i < ElementCount( ); i++ )
            {
                if( iElementArray[ i ]->iName->Compare( _L("Text") ) == 0 )
                {
                    
                    TLex lex( *iElementArray[ i ]->iText );
                    int result = lex.Val( value );
                    return result == KErrNone ? value : 0.00;
                }
            }
        }
        return value;
    }
    int GetElementTextAsInt( )
    {
        int value = -1;
        if( iName->Compare( _L("Text") ) == 0 )
        {
            TLex lex( *iText );
            int result = lex.Val( value );
            return result == KErrNone ? value : -1;
        }
        else
        {
            for( TInt i = 0; i < ElementCount( ); i++ )
            {
                if( iElementArray[ i ]->iName->Compare( _L("Text") ) == 0 )
                {
                    
                    TLex lex( *iElementArray[ i ]->iText );
                    int result = lex.Val( value );
                    return result == KErrNone ? value : -1;
                }
            }
        }
        return -1;
    }
    
    inline void SetText( const TDesC & aText )
    {
        delete iText;
        
        iText = HBufC::NewL( aText.Length( ) );
        iText->Des( ).Copy( aText );
    }
    
    inline TInt ElementCount( )
    {
        return iElementArray.Count( );
    }
    
    void Append( CElement * c );
    void Insert( CElement * c, TInt aPos );
    void DeleteElement( TInt id );
    CElement *GetElement( TInt id );
    CElement *GetParent( )
    {
        return iParent;
    }
    
    void SetParent( CElement * parent )
    {
        iParent = parent;
    }
    
    CElement *GetElement( TInt id, const TDesC & elmtName );
    CElement *GetElement( const TDesC & elmtPath );

    void AddLength( TInt len )
    {
        if( iEndPos == 0 )
            iEndPos = iStartPos + len;
        else
            iEndPos += len;
        if( GetParent( ) )
        {
            GetParent( )->AddLength( len );
        }
    }
    
    void DumpContents( )
    {
    }
    
public:
    TInt iStartPos;
    TInt iEndPos;

protected:
    inline explicit CElement( const TDesC & name )
    {
        iName = HBufC::NewL( name.Length( ) );
        iName->Des( ).Copy( name );
    }
    
    CElement( )
    {
        
    }
    
    RPointerArray< CElement > iElementArray;
    CElement *iParent;
    //CBrowserFont *iFont;
    HBufC *iName;
};
_LIT16(wml, "wml");
typedef CElement CWml;

template< class Element > class RStack
{
public:
    ~RStack( );
    void Push( Element * e );
    Element *Pop( );
    TInt Count( );
    void Close( );
    void Reset( );
    void ResetAndDestroy( );

    RPointerArray< Element > iElementArray;
};

typedef RStack< CElement > RElementStack;

template< class Element > RStack< Element >::~RStack( )
{
    iElementArray.Close( );
}

template< class Element > void RStack< Element >::Close( )
{
    iElementArray.Close( );
}

template< class Element > void RStack< Element >::Reset( )
{
    iElementArray.Reset( );
}

template< class Element > void RStack< Element >::ResetAndDestroy( )
{
    iElementArray.ResetAndDestroy( );
}

template< class Element > void RStack< Element >::Push( Element * e )
{
    iElementArray.Append( e );
}

template< class Element > Element * RStack< Element >::Pop( )
{
    if( iElementArray.Count( ) > 0 )
    {
        Element *e = iElementArray[ iElementArray.Count( ) - 1 ];
        
        iElementArray.Remove( iElementArray.Count( ) - 1 );
        return e;
    }
    else
        return NULL;
}

template< class Element > TInt RStack< Element >::Count( )
{
    return iElementArray.Count( );
}

class CDomBuilder : public CBase, public MSAXEventListener
{
public:
    ~CDomBuilder( );
    static CDomBuilder* NewL( );
    static CDomBuilder* NewLC( );
private:
    CDomBuilder( );
    void ConstructL( );
public:
    CElement *ParseL( const TDesC & aDocument );

    void Reset( );
    //CElement* GetWml(){return iCurrentElement;iCurrentElement = NULL;};
    void GetFocusArray( RPointerArray< CElement > &aArray )
    {
        for( TInt i = 0; i < iFocusArray.Count( ); i++ )
        {
            aArray.Append( iFocusArray[ i ] );
        }
        
        iFocusArray.Reset( );
    }
    const TDesC & GetLastError( );

protected:
    void StartElement( const TDesC & aName, const TDesC & aNamespace, const RAttributeList & aAttrList );
    void EndElement( const TDesC & aName, const TDesC & aNamespace );
    void FreeText( const TDesC & aText );
    void ParsingError( const TDesC & aReason );
    void Comment( const TDesC & aCommentText );

private:
    CElement * iCurrentElement;
    RElementStack iStack;

    RPointerArray< CElement > iFocusArray;
    RMutex mutex;

    fXmlParser /*CEAXPParser */* iParser;
    TBool bRuning;
    HBufC* iLastError;
};
#endif /*fWML_H_ */

